package io.cloud.tec.config;

import io.cloud.tec.project.anno.Page;
import io.cloud.tec.project.model.PageResult;
import io.cloud.tec.project.model.Result;
import io.cloud.tec.project.util.PageUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.List;

@RestControllerAdvice
public class ResponseBodyHandler extends AbstractMappingJacksonResponseBodyAdvice {

    /**
     * org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#initControllerAdviceCache()
     *
     * 如果在@ControllerAdvice注解修饰的类中使用@InitBinder注解，
     * 此时@InitBinder注解修饰的方法所做的事情全局生效
     * （前提是@ControllerAdvice注解没有设置basePackages字段）；
     *
     * 如果在@Controller注解修饰的类中使用@InitBinder注解，
     * 此时@InitBinder注解修饰的方法所做的事情仅对当前Controller生效。
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
//        MutablePropertyValues propertyValues = new MutablePropertyValues();
//        propertyValues.addPropertyValue("!createTime", Instant.now().toEpochMilli());
//        binder.bind(propertyValues);
//        binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
    }

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return super.supports(returnType, converterType);
    }

    @Override
    protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
        Object body = bodyContainer.getValue();
        if (body instanceof Result || body instanceof PageResult) {
            return;
        } else {
//            String apiUrl;
//            if (contextPath != null && contextPath != "") {
//                apiUrl = contextPath + "/api";
//            } else {
//                apiUrl = "/api";
//            }

            HttpServletRequest httpServletRequest = ((ServletServerHttpRequest) request).getServletRequest();
            String url = httpServletRequest.getRequestURI();
            // api开头的url才进行包装
            if (!url.startsWith("/api")) {
                return;
            }
            // String类型特别处理，防止发生类型转换异常
            if (body instanceof String) {
                bodyContainer.setValue(Result.success(body));
//            } else if (returnType.getParameterType().isAssignableFrom(Collection.class)) {
            } else if (returnType.hasMethodAnnotation(Page.class) && body instanceof List) {
                bodyContainer.setValue(PageUtils.toPage((List) body));
            } else {
                bodyContainer.setValue(Result.success(body));
            }
        }
    }
}
